package org.xbdframework.dao.core.sqlandparam.builder;

import java.util.HashMap;
import java.util.Map;

import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import org.xbdframework.dao.core.BasePo;
import org.xbdframework.dao.core.sqlandparam.AbstractSqlAndParamBuilder;
import org.xbdframework.jdbc.core.SqlAndParam;

public class UpdateSqlAndParamBuilder<T extends BasePo>
		extends AbstractSqlAndParamBuilder<T> {

	public UpdateSqlAndParamBuilder(T po) {
		super(po);
	}

	@Override
	public SqlAndParam<Object[]> buildArraySql() {
		StringBuilder sb = createPreUpdateSql();

		sb.append(" " + SQL_KEYWORD_WHERE + " ").append(this.po.getPkName())
				.append(" = ?");

		Object[] params = mergeMapParameter(createSetObjectParams(),
				buildPkWhereArrayParams());

		return new SqlAndParam<>(sb.toString(), params);
	}

	@Override
	public SqlAndParam<Object[]> buildArraySql(String where, Object[] params) {
		StringBuilder sb = createPreUpdateSql();

		Object[] tempParams = mergeMapParameter(createSetObjectParams(), params);

		return new SqlAndParam<>(sb.toString(), tempParams);
	}

	@Override
	public SqlAndParam<Map<String, Object>> buildMapSql() {
		StringBuilder sb = createPreUpdateSql();

		sb.append(" " + SQL_KEYWORD_WHERE + " ").append(this.po.getPkName())
				.append(" = :").append(this.po.getPkName());

		Map<String, Object> params = mergeMapParameter(createSetMapParams(),
				buildPkWhereMapParams());

		return new SqlAndParam<>(sb.toString(), params);
	}

	@Override
	public SqlAndParam<Map<String, Object>> buildMapSql(String where,
			Map<String, Object> paramMap) {
		StringBuilder sb = createPreUpdateSql();

		sb.append(escapeWhere(where));

		Map<String, Object> params = mergeMapParameter(createSetMapParams(), paramMap);

		return new SqlAndParam<>(sb.toString(), params);
	}

	@Override
	public SqlAndParam<SqlParameterSource> buildSqlParameterSourceSql() {
		StringBuilder sb = createPreUpdateSql();

		sb.append(" " + SQL_KEYWORD_WHERE + " ").append(this.po.getPkName())
				.append(" = :").append(this.po.getPkName());

		return new SqlAndParam<>(sb.toString(),
				new BeanPropertySqlParameterSource(this.po));
	}

	@Override
	public SqlAndParam<SqlParameterSource> buildSqlParameterSourceSql(String where,
			SqlParameterSource params) {
		StringBuilder sb = createPreUpdateSql();

		sb.append(escapeWhere(where));

		SqlParameterSource parameterSourceResult = mergeParameterSource(
				new BeanPropertySqlParameterSource(this.po), params);

		return new SqlAndParam<>(sb.toString(), parameterSourceResult);
	}

	private StringBuilder createPreUpdateSql() {
		StringBuilder sb = new StringBuilder("update ").append(getTableName());
		sb.append(" set ");

		int i = 0;
		for (String column : this.setColumns) {
			if (i > 0) {
				sb.append(", ");
			}

			sb.append(column).append(" = :").append(column);
			i++;
		}

		return sb;
	}

	private Object[] createSetObjectParams() {
		return this.setValues.toArray(new Object[this.setValues.size()]);
	}

	private Map<String, Object> createSetMapParams() {
		Map<String, Object> params = new HashMap<>();

		for (int i = 0; i < this.setColumns.size(); i++) {
			params.put(this.setColumns.get(i), this.setValues.get(i));
		}

		return params;
	}

}
